home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Grand Slam 3
/
Grand Slam 3.iso
/
026
/
imphob10.arj
/
IMP10_EX.ARJ
/
W_GEMMIS.ARJ
/
MEM32IMP.INC
< prev
Wrap
Text File
|
1995-05-15
|
22KB
|
1,076 lines
;║ A FLAT REAL MODE INITIALIZER EXAMPLE
;║ ────────────────────────────────────
;║
;║ Compliant with RAW, XMS or EMS environments
;║
;║ Documentation used :
;║ microsoft eXtended Memory Specification (XMS) ver 3.0
;║ lotus/intel/microsoft Expanded Memory Specification (EMS) ver 4.0
;║ microsoft undocumented Global EMM Import Specification (GEMMIS) ver 1.11
;║
;║ Documentation needed :
;║ standard method for detecting drivers which use the VDISK allocation scheme
;║ (this is an official publication by microsoft but I don't have it)
;║
;║ (c) Walken / IMPACT Studios in 1995 - for publication in Imphobia #10
;╚════════════════════════════════════════════════════════════════════════════
;│ Legal stuff :
;│ This document can be copyed only when unmodified and in its entirety.
;│ Commercial use - including commercial distribution or use in commercial
;│ software - is strictly prohibited without the written permission
;│ of the author.
;│ The author excludes any and all implied warranties, including warranties
;│ of merchantability and fitness for a particular purpose. The author
;│ should have no liability for special, incidental, or consequential
;│ damages arising out or resulting from the use or modification of this
;│ source code.
;└────────────────────────────────────────────────────────────────────────────
;║ You can contact the author at the following address :
;║ Walken / IMPACT Studios
;║ Michel LESPINASSE - 18 rue Jean Giono - 80090 Amiens - FRANCE
;╚════════════════════════════════════════════════════════════════════════════
.data
import_buffer df 1
device_EMMXXXX0 db 'EMMXXXX0',0 ;EMM device driver name
EMS_handle_name db '■WaLKeN■'
nb_XMS_handle dw 0
nb_available_memory dw 0
native_V86 db 0 ;system mode 0=real 1=V86
local_A20 db 0 ;A20 line touched by XMS 0=no 1=yes
EMS_alloc db 0 ;EMS handle allocated 0=no 1=yes
no_native db 0 ;running with CPU mode <> system mode 0=no 1=yes
flat_enabled db 0 ;running in FRM 0=no 1=yes
NMI_state_touched db 0 ;touched NMI state 0=no 1=yes
int15_hook db 0 ;hooked int 15 0=no 1=yes
ptr_GDT label fword
dw 39,o dgroup:GDT,0,0
GDT dw 4 dup(0) ;NULL selector
dw 0ffffh,0,9a00h,0 ;_text selector
dw 0ffffh,0,9200h,0 ;data16 selector
dw 4 dup(0) ;unused
dw 0ffffh,0,9200h,8fh ;data32 selector
_text_selector=8
ptr_IDT_native label fword
dw 3ffh,0,0,0
ptr_IDT_flatreal label fword
dw 3ffh,offset ds:IDT_flatreal,0,0
ext_mem_move dd 1024
dw 0
dd buffer_mem_move
dw ?
dd ?
msg_GEMMIS db "GEMMIS protocol denyes access to the real mode$"
msg_no_GEMMIS db "GEMMIS protocol not available$"
msg_bad_GEMMIS db "GEMMIS data anomaly$"
msg_EMM4 db "Your EMM is too old, you'll need EMS 4.0 or higher$"
msg_XMS3 db "Your XMS is too old, you'll need XMS 3.0 or higher$"
msg_hook db "XMS driver hook does not follow XMS 3.0 standard$"
msg_a20 db "Cannot enable the A20 gate$"
msg_XMS_alloc db "XMS memory allocation error$"
msg_EMS_alloc db "EMS memory allocation error$"
msg_fragment db "High memory is fragmented in more than 256 blocks$"
msg_nomem db "Not enough free memory$"
msg_badmem db "Memory allocation error$"
msg_verify_pages db "Cannot verify allocated pages$"
msg_error_pages db "Error in allocated pages$"
msg_CPU db "You'll need a 386 or better to run this program$"
msg_V86_no_XMS db "V86 mode with RAW environment is not supported$"
msg_v86 db "unable to switch to V86 mode for interrupts$"
memory_manager_name db 40 dup(' '),'$'
.data?
buffer_mem_move db 1024 dup(?)
available_memory_table dd 257 dup(?,?)
XMS_handle dw 256 dup(?)
EMS_handle dw ?
EMS_size dw ?
modeswitch dd ?
himem_driver dd ?
XMS_hook_base dd ?
XMS_hook_addr dd ?
old_int15 dd ?
exit_msg dw ?
XMS_hook_jmpval db ?
NMI_state db ?
.code
.486p
;****************************************;
;* memory manager init / alloc function *;
;****************************************;
mem32_init:
push cs
pop ds
;* test proc >= 386
mov dx,o msg_CPU
pushf
pop ax
or ah,0f0h
push ax
popf
pushf
pop ax
and ah,0f0h
jnz no_immediate_exit ;long jz instruct not supported on the 286
jmp immediate_exit
no_immediate_exit:
;* test proc >= 486, include it if your proggy does not support 386 processor
; pushfd
; pop eax
; mov ebx,eax
; xor eax,40000h
; push eax
; popfd
; pushfd
; pop eax
; xor eax,ebx
; jz immediate_exit ;it's a 386
; push ebx
; popfd
;* test V86 mode
smsw ax
test al,1
jz no_V86
inc native_V86
;* windows fake init
mov exit_msg,o msg_GEMMIS
call open_ouinedoze
;* test EMS driver
mov exit_msg,o msg_no_GEMMIS
mov ax,3d00h
mov dx,o device_EMMXXXX0
int 21h ;open handle
jc exitmsg
mov bx,ax
mov ax,4400h
int 21h ;get device information
jc exitmsg
not dx
test dx,4080h
jnz exitmsg
mov ax,4407h
int 21h ;get output status
jc exitmsg
inc al
jnz exitmsg
mov ah,3eh
int 21h ;close handle
;* test EMS version >= 4.0
mov ah,46h
int 67h ;get EMM version
mov dx,o msg_EMM4
or ah,ah
jnz exit
cmp al,40h
jb exit
no_V86:
;* test XMS driver
mov ax,4300h
int 2fh ;XMS install test
cmp al,80h
jne no_xms
mov ax,4310h ;get XMS call adress
int 2fh
mov w himem_driver,bx
mov w himem_driver+2,es
;* test XMS version >= 3.0
push bx
xor ax,ax
call himem_driver ;get XMS version
mov dx,o msg_XMS3
cmp ah,3
jb exit
pop bx
;* XMS hook locate (code from XMS 3.0 specification)
locate_xms_hook:
mov dx,o msg_hook
mov cx,w es:[bx]
cmp cl,0ebh ;short jump
je found_xms_hook
cmp cl,0eah ;far jump
jne exit
les bx,d es:[bx+1]
jmp locate_xms_hook
found_xms_hook:
mov eax,d es:[bx+2]
and eax,0ffffffh
xor eax,909090h ;3x nop
jnz exit
mov al,ch
mov XMS_hook_jmpval,al
add al,2
add ax,bx
mov w XMS_hook_base,bx
mov w XMS_hook_base+2,es
mov w XMS_hook_addr,ax
mov w XMS_hook_addr+2,es
;* enable A20 gate (XMS)
push bx
mov ah,5
call himem_driver ;local enable A20
mov dx,o msg_a20
dec ax
jnz exit
pop bx
inc local_A20
;* XMS hook install
cli
mov b es:[bx],0eah ;far jump
mov w es:[bx+1],o cs:XMS_hook
mov w es:[bx+3],cs
sti
;* init check pages buffer
push cs
pop es
mov di,o cs:buffer_mem_move
mov cx,64
call fill_check_page
;* XMS allocate
xor edi,edi
XMS_alloc:
mov exit_msg,o msg_XMS_alloc
xor bl,bl ;grumbl
mov ah,8
call himem_driver ;query free XMS memory
or ax,ax ;grumbl
jz XMS_allocated
or bl,bl ;grumbl
jnz XMS_allocated
add ax,64
mov dx,ax
XMS_alloc_block:
push dx
mov ah,9
call himem_driver ;allocate XMS block
dec ax
jz XMS_block_allocated
pop dx
sub dx,64
jbe XMS_allocated
jmp XMS_alloc_block
XMS_block_allocated:
mov XMS_handle[edi*2],dx
mov d ext_mem_move[12],0
mov w ext_mem_move[10],dx
inc di
mov nb_XMS_handle,di
mov ah,0ch
call himem_driver ;lock XMS block
dec ax
jnz exitmsg
;* write to the XMS block for further check of allocated pages
mov exit_msg,o msg_verify_pages
pop cx
push cx
push bx
test_XMS_block:
mov ah,0bh
mov si,o ext_mem_move
call himem_driver ;copy to XMS block
dec ax
jnz exitmsg
add d ext_mem_move[12],1024
loop test_XMS_block
pop bx
;* save adress of the XMS block
xor eax,eax
pop ax
shl eax,10
shl edx,16
mov dx,bx
add eax,edx
mov available_memory_table[edi*8-8],edx
mov available_memory_table[edi*8-4],eax
cmp di,256
jb XMS_alloc
XMS_allocated:
mov nb_available_memory,di
;* if not native V86 mode skip EMS & GEMMIS
cmp native_V86,0
jz flat
;* EMS allocate & set handle name
mov exit_msg,o msg_EMS_alloc
mov ah,42h
int 67h ;get unallocated page count
or ah,ah
jnz exitmsg
or bx,bx
jz EMS_allocated
mov EMS_size,bx
mov ah,43h
int 67h ;allocate pages
or ah,ah
jnz exitmsg
inc EMS_alloc
mov EMS_handle,dx
mov ax,5301h
mov si,o ds:EMS_handle_name
int 67h ;set handle name
or ah,ah
jnz exitmsg
;* write to the EMS block for further check of allocated pages
mov exit_msg,o msg_verify_pages
xor ecx,ecx
mov cx,bx
mov ah,47h
int 67h ;save page map
or ah,ah
jnz exitmsg
mov ah,41h
int 67h ;get page frame address
or ah,ah
jnz exitmsg
mov es,bx
check_EMS_page:
mov ax,4400h
lea bx,[ecx-1]
int 67h ;map handle page
or ah,ah
jnz exitmsg
xor di,di
push cx
mov cx,1024
call fill_check_page
pop cx
loop check_EMS_page
mov ah,48h
int 67h ;restore page map
or ah,ah
jnz exitmsg
EMS_allocated:
;* GEMMIS IOCTL
mov exit_msg,o ds:msg_no_GEMMIS
mov ax,3d00h
mov dx,offset cs:device_EMMXXXX0
int 21h ;open device
jc exitmsg ;device does not exist
mov bx,ax
mov ax,4402h
mov cx,6
mov dx,offset ds:import_buffer
int 21h ;IOCTL read
jc exitmsg ;cannot read device
cmp ax,cx
jne exitmsg ;cannot read device
mov ah,3eh
int 21h ;close device
;* test GEMMIS version >= 1.0
cmp b import_buffer+4,1
jb exitmsg
;* real mode switch
mov exit_msg,o ds:msg_GEMMIS
call switch_to_real
;* flat mode switch
call first_enable_flat
;* GEMMIS data decode : find physical addresses allocated to the EMS block
mov exit_msg,o msg_bad_GEMMIS
xor ax,ax
mov es,ax
mov esi,d import_buffer
add esi,397
movzx ecx,b es:[esi-2]
shl cx,4
add esi,ecx ;skip UMB frame descriptors
push esi ;here es:esi points to first EMS handle info record
cmp EMS_alloc,0
jz no_EMS_handle
xor ecx,ecx
mov cl,es:[esi-1]
inc cx ;number of EMS handle info records
sub esi,16
find_EMS_handle:
dec cx
jz exitmsg
add esi,16
cmp d es:[esi+2],'LaW■'
jne find_EMS_handle
cmp d es:[esi+6],'■NeK'
jne find_EMS_handle
mov cx,es:[esi+10]
mov esi,es:[esi+12] ;page map for allocated EMS block
cmp EMS_size,cx
jne exitmsg
shl cx,2
xor edi,edi
mov di,nb_available_memory
lods d es:[esi]
and ax,0f000h
mov ebx,eax
jmp contiguous
find_contiguous:
lods d es:[esi]
and ax,0f000h
cmp eax,edx
je contiguous
mov available_memory_table[edi*8],ebx
mov available_memory_table[edi*8+4],edx
mov dx,o msg_fragment
inc di
cmp di,256
je exit
mov ebx,eax
contiguous:
lea edx,[eax+1000h]
loop find_contiguous
mov available_memory_table[edi*8],ebx
mov available_memory_table[edi*8+4],edx
inc di
mov nb_available_memory,di
no_EMS_handle:
pop esi
;* GEMMIS data decode : save memory manager name if version >= 1.11
mov ax,w import_buffer[4]
xchg al,ah
cmp ax,10ah
jb dont_save_name
push ax
movzx cx,b es:[esi-1] ;number of EMS handle info records to skip
shl cx,4
add esi,ecx
xor cx,cx
mov cl,b es:[esi+8]
lea esi,[esi+ecx*8] ;skip free page entryes
mov cl,b es:[esi+9]
lea ecx,[ecx*2+ecx]
lea esi,[esi+ecx*4] ;skip XMS handle info records
xor cx,cx
mov cl,b es:[esi+10]
lea esi,[esi+ecx*4+11] ;skip free UMB info records
pop ax
cmp ax,10bh
ja dont_check_size
mov edi,d import_buffer
mov cx,es:[edi+2]
lea edi,[edi+ecx]
jb version_110
sub edi,40
version_110:
cmp esi,edi
jne exitmsg
cmp ax,10ah
je dont_save_name
dont_check_size:
mov di,o ds:memory_manager_name
mov cx,10
copy_name:
lods d es:[esi]
mov [di],eax
add di,4
loop copy_name
dont_save_name:
;* goto init_return
jmp init_return
no_xms:
;* exit if native V86 mode and no XMS manager
mov dx,o msg_V86_no_XMS
cmp native_V86,0
jnz exit
;* enable A20 gate (RAW) / this code is from TRAN aka Thomas Pytel
cli
xor ax,ax ;set A20 test segments 0 and 0ffffh
mov fs,ax
dec ax
mov gs,ax
call enable_A20_test
jz enable_A20_done
in al,92h ;PS/2 A20 enable
or al,2
jmp $+2
jmp $+2
jmp $+2
out 92h,al
call enable_A20_test
jz enable_A20_done
call enable_A20_kb_wait ;AT A20 enable
jnz wait_enable_A20
mov al,0d1h
out 64h,al
call enable_A20_kb_wait
jnz wait_enable_A20
mov al,0dfh
out 60h,al
call enable_A20_kb_wait
wait_enable_A20: ;wait for A20 to enable
mov cx,800h
loop_wait_enable_A20:
call enable_A20_test
jz enable_A20_done
in al,40h
jmp $+2
jmp $+2
jmp $+2
in al,40h
mov ah,al
A20_wait_tick:
in al,40h
jmp $+2
jmp $+2
jmp $+2
in al,40h
cmp al,ah
je A20_wait_tick
loop loop_wait_enable_A20
mov dx,o msg_a20
jmp exit
enable_a20_done:
sti
;* get amount of RAW memory / this code is from TRAN aka Thomas Pytel
mov ah,88h
int 15h ;get RAW memory size
or ax,ax
jz flat
movzx eax,ax
shl eax,10
add eax,100000h
mov available_memory_table[4],eax
les bx,dword ptr fs:[4*19h]
mov eax,100000h
cmp dword ptr es:[bx+12h],'SIDV'
jne no_vdisk_1
mov eax,dword ptr es:[bx+2ch]
add eax,0fh
and eax,0fffff0h
no_vdisk_1:
cmp dword ptr gs:[13h],'SIDV'
jne no_vdisk_2
movzx ebx,w gs:[2eh]
shl ebx,10
cmp eax,ebx
ja no_vdisk_2
mov eax,ebx
no_vdisk_2:
cmp eax,available_memory_table[4]
jae flat
mov available_memory_table[0],eax
inc nb_available_memory
;* reserve all available RAW memory
mov eax,fs:[15h*4]
mov old_int15,eax
mov w fs:[15h*4+2],cs
mov w fs:[15h*4+2],o cs:int15_handler
inc int15_hook
flat:
;* flat mode switch
call first_enable_flat
init_return:
;* group contiguous allocated physical memory adresses
push cs
pop es
mov exit_msg,o msg_badmem
xor ecx,ecx
sort_available_memory:
mov dx,o msg_nomem
mov cx,nb_available_memory
dec cx
js exit
jz available_memory_grouped
sort_available_memory_pass:
mov eax,available_memory_table[ecx*8-8]
cmp eax,available_memory_table[ecx*8]
jna available_memory_sorted
xchg eax,available_memory_table[ecx*8]
mov available_memory_table[ecx*8-8],eax
mov eax,available_memory_table[ecx*8-4]
xchg eax,available_memory_table[ecx*8+4]
mov available_memory_table[ecx*8-4],eax
jmp sort_available_memory
available_memory_sorted:
loop sort_available_memory_pass
group_available_memory:
mov cx,nb_available_memory
dec cx
jz available_memory_grouped
group_available_memory_pass:
mov eax,available_memory_table[ecx*8-4]
cmp eax,available_memory_table[ecx*8]
ja exitmsg
jb available_memory_block_grouped
lea di,available_memory_table[ecx*8-4]
lea si,[di+8]
mov cx,nb_available_memory
lea cx,available_memory_table[ecx*8]
sub cx,si
rep movsb
dec nb_available_memory
jmp group_available_memory
available_memory_block_grouped:
loop group_available_memory_pass
available_memory_grouped:
;* check allocated pages if not RAW
cmp local_A20,0
jz dont_check_pages
xor ax,ax
mov es,ax
xor ecx,ecx
mov cx,nb_available_memory
mov dx,o msg_error_pages
check_allocated_pages:
mov esi,available_memory_table[ecx*8-8]
mov ebx,available_memory_table[ecx*8-4]
sub ebx,esi
shr ebx,4
check_pages:
lods d es:[esi]
cmp eax,'PMI■'
jne exit
lods d es:[esi]
cmp eax,' TCA'
jne exit
lods d es:[esi]
cmp eax,'dutS'
jne exit
lods d es:[esi]
cmp eax,'■soi'
jne exit
dec ebx
jnz check_pages
loop check_allocated_pages
dont_check_pages:
;* install flat real mode interrupt handler
cmp native_V86,0
jz no_flatreal_handler
lidt cs:ptr_IDT_flatreal
sti
no_flatreal_handler:
ret
;*************************************************;
;* memory manager switch to native mode function *;
;*************************************************;
mem32_native:
cmp native_V86,0
jz no_native_switch
mov exit_msg,o ds:msg_V86
cli
lidt cs:ptr_IDT_native
call disable_flat
call switch_to_v86
jc exitmsg
call close_ouinedoze
no_native_switch:
ret
;****************************************************;
;* memory manager switch to flat real mode function *;
;****************************************************;
mem32_flatreal:
cmp native_V86,0
jz no_flatreal_switch
mov exit_msg,o ds:msg_V86
call open_ouinedoze
call switch_to_real
call enable_flat
lidt cs:ptr_IDT_flatreal
sti
no_flatreal_switch:
ret
;*********************************************;
;* memory manager exit / unallocate function *;
;*********************************************;
; DS:DX = exit message to display
exit:
mov exit_msg,dx
exitmsg:
;* disable flat mode
cmp flat_enabled,0
jz flat_disabled
pushf
call disable_flat
popf
flat_disabled:
;* native mode switch
cmp no_native,0
jz native_exit
call switch_to_v86
sti
native_exit:
;* restore NMI state
cmp NMI_state_touched,0
jz no_NMI_state
mov al,NMI_state
out 70h,al ;restore NMI state
rept 3
jmp $+2
endm
in al,71h
no_NMI_state:
;* unallocate RAW
cmp int15_hook,0
jz no_int15_hook
xor ax,ax
mov es,ax
mov eax,old_int15
mov es:[15h*4],eax
no_int15_hook:
;* disable A20 gate (RAW) - not done yet (and not really necessary)
;* EMS unalloc
cmp EMS_alloc,0
jz EMS_unallocated
mov ah,45h
mov dx,EMS_handle
int 67h ;unallocate pages
EMS_unallocated:
;* XMS unalloc
xor ecx,ecx
mov cx,nb_XMS_handle
jcxz XMS_unallocated
XMS_unalloc:
mov ah,0dh
mov dx,XMS_handle[ecx*2-2]
call himem_driver ;unlock XMS block
mov ah,0ah
call himem_driver ;release XMS block
loop XMS_unalloc
XMS_unallocated:
;* local disable A20 & XMS hook desinstall
cmp local_A20,0
jz no_A20_disable
mov al,0ebh
mov ah,XMS_hook_jmpval
les bx,XMS_hook_base
cli
mov d es:[bx+1],90909090h
mov w es:[bx],ax
sti
mov ah,6
call himem_driver ;local disable A20
no_A20_disable:
;* windows fake exit
cmp native_V86,0
jz no_fake_exit
call close_ouinedoze
no_fake_exit:
mov dx,exit_msg
immediate_exit:
mov ah,9
int 21h ;display exit message
mov ax,4c00h
int 21h ;exit without errorlevel
;***********************************************;
;* memory manager interrupt handling functions *;
;***********************************************;
IDT_flatreal equ this word ;flat real mode interrupt table
irpc hex,<0123456789abcdef>
irpc unit,<0123456789abcdef>
dw it&hex&&unit,_text
endm
endm
num=0 ;flat real mode interrupt handlers
irpc hex,<0123456789abcdef>
irpc unit,<0123456789abcdef>
it&hex&&unit:
push eax
mov al,num
jmp it
num=num+1
endm
endm
it:
lidt cs:ptr_IDT_native
mov cs:automodif_int+1,al
push ebx
push ecx
push edx
push esi
push edi
push ebp
push ds
push es
push fs
push gs
mov exit_msg,o ds:msg_V86
call disable_flat
call switch_to_v86
jc exitmsg
call close_ouinedoze
pop gs
pop fs
pop es
pop ds
pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
push esp
movzx esp,sp
push w ss:[esp+8] ;flags, tricky !
popf
automodif_int db 0cdh,0 ;call the old interrupt handler
pushf
pop w ss:[esp+8] ;flags, tricky !
cli
pop esp
push eax
push ebx
push ecx
push edx
push esi
push edi
push ebp
push ds
push es
push fs
push gs
mov exit_msg,o ds:msg_V86
call open_ouinedoze
call switch_to_real
call enable_flat
pop gs
pop fs
pop es
pop ds
pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
lidt cs:ptr_IDT_flatreal
iret
;*************************************;
;* memory manager internal functions *;
;*************************************;
first_enable_flat:
xor eax,eax
mov ax,cs
shl eax,4
add dword ptr ptr_GDT+2,eax
add dword ptr ptr_IDT_flatreal+2,eax
mov si,offset cs:GDT
mov word ptr [si+_text_selector+2],ax
shr eax,16
mov byte ptr [si+_text_selector+4],al
cli
in al,70h
rept 3
jmp $+2
endm
mov ah,al
in al,71h
rept 3
jmp $+2
endm
mov al,ah
mov NMI_state,al
inc NMI_state_touched
or al,80h
out 70h,al ;disable NMI
rept 3
jmp $+2
endm
in al,71h
enable_flat:
pushf
cli
lgdt fword ptr ptr_GDT
switch_prot _text,@@pmode
@@pmode:
mov ax,32
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
switch_real _text,@@rmode
@@rmode:
push cs
pop ds
popf
inc flat_enabled
ret
disable_flat:
cli
switch_prot _text,@@pmode
@@pmode:
mov ax,16
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
switch_real _text,@@rmode
@@rmode:
push cs
pop ds
dec flat_enabled
ret
switch_to_real:
xor ax,ax
cli
call modeswitch
push cs
pop ds
jc exitmsg
inc no_native
ret
switch_to_v86:
mov ax,1
cli
call cs:modeswitch
push cs
pop ds
mov no_native,0
ret
open_ouinedoze:
mov ax,1605h
xor bx,bx
mov cx,bx
mov dx,bx
mov si,bx
mov di,30bh ;version number 3.11
mov ds,bx
mov es,bx
int 2fh ;set device name to "EMMXXXX0" & return entry point addr
push ds
push cs
pop ds
pop ax
or cx,cx
jnz exitmsg ;cannot run windows
mov w modeswitch+2,ax
mov w modeswitch,si
or ax,si
jz exitmsg ;modeswitch not available
ret
close_ouinedoze:
mov ax,1606h
xor dx,dx
int 2fh ;restore device name
ret
fill_check_page:
mov eax,'PMI■'
stosd
mov eax,' TCA'
stosd
mov eax,'dutS'
stosd
mov eax,'■soi'
stosd
loop fill_check_page
ret
XMS_hook:
jmp $+5
nop
nop
nop
cmp al,3
jb @@XMS_okay
cmp al,6
ja @@XMS_okay
mov ax,1
retf ;disable A20 control functions
@@XMS_okay:
jmp cs:XMS_hook_addr
int15_handler:
cmp ah,88h
je reserve_high_memory
jmp old_int15
reserve_high_memory:
xor ax,ax
iret
enable_A20_kb_wait: ;wait for safe to write to 8042
xor cx,cx
loop_enable_A20:
jmp $+2
jmp $+2
jmp $+2
in al,64h
test al,2
loopnz loop_enable_A20
ret
enable_A20_test: ;test for enabled A20
mov al,fs:[0]
mov ah,al
not al
xchg al,gs:[10h]
cmp ah,fs:[0]
mov gs:[10h],al
ret
;* init
; switch natif
; message
; [switch frm]
; deinit / release
;* retour